// Package initialize
// Title  viper.initialize 配置文件读取
// Description  初始化加载配置参数
// Author  alittlexincan@163.com 2024/07/22 11:36
// update  alittlexincan@163.com 2024/07/22 11:36
package initialize

import (
	"encoding/json"
	"log"
	"strings"
	"time"

	remote "github.com/liangboceo/nacos-viper-remote"
	"github.com/spf13/viper"
	_ "github.com/spf13/viper/remote"
	"xincan.com.cn/tarot-go-framework/config"
	"xincan.com.cn/tarot-go-framework/global"
)

var (
	fileName = "config"
	suffix   = "yaml"
	provider = "nacos"
)

// initLocalConfig
// Title    			配置本地本地读取yaml
// Description   		配置本地本地读取yaml
// Auth      			alittlexincan@163.com       			时间（2024/07/17 11:36）
// Update    			alittlexincan@163.com       			时间（2024/07/17 11:36）
// Return    			*viper.Viper						    viper解析器实例
func initLocalConfig() *viper.Viper {
	viper.SetConfigName(fileName)
	viper.AddConfigPath(".")
	viper.SetConfigType(suffix)
	err := viper.ReadInConfig()
	if err != nil {
		log.Fatalf("Viper插件初始化失败: %s+v", err)
	}
	log.Println("Viper插件读取配置数据位置为:", viper.Get("business.viper"))
	var appConfig config.AppConfig
	err = viper.Unmarshal(&appConfig)
	if err != nil {
		log.Fatalf("Viper插件配置文件映射对象失败: %+v", err)
	}
	global.Viper = viper.GetViper()
	global.AppConfig = &appConfig
	configData, _ := json.Marshal(&appConfig)
	log.Printf("Viper插件配置文件映射对象成功 %+v\n", string(configData))

	return global.Viper
}

// InitGlobalConfig
// Title    			配置读取yaml
// Description   		配置读取yaml
// Param    			logger *zap.Logger						日志实例
// Auth      			alittlexincan@163.com       			时间（2024/07/17 11:36）
// Update    			alittlexincan@163.com       			时间（2024/07/17 11:36）
// Return    			*viper.Viper, *viper.Viper     			yaml 解析器实例
func InitGlobalConfig() *viper.Viper {

	localViper := initLocalConfig()

	if localViper.GetString("business.viper") == "local" {
		return localViper
	}

	log.Println("=== Viper 读取远程配置数据 ===")

	// 自定义远程读取配置
	remoteViper := viper.New()

	// 匹配正则表达式, 获取协议和IP地址
	nacosIp := localViper.GetString("nacos.ip")
	matches := []string{
		nacosIp,
		strings.Split(nacosIp, "://")[0],
		strings.Split(nacosIp, "://")[1],
	}

	remote.SetOptions(&remote.Option{
		Url:         matches[2],
		Port:        localViper.GetUint64("nacos.port"),
		NamespaceId: localViper.GetString("nacos.config.namespaceId"),
		GroupName:   localViper.GetString("nacos.config.group"),
		Config: remote.Config{
			DataId: localViper.GetString("nacos.config.dataId"),
		},
		Auth: &remote.Auth{
			Enable:   true,
			User:     localViper.GetString("nacos.username"),
			Password: localViper.GetString("nacos.password"),
		},
	})

	// 添加重试机制
	maxRetries := 5
	for i := 0; i < maxRetries; i++ {
		err := remoteViper.AddRemoteProvider(provider, localViper.GetString("nacos.ip"), "")
		remoteViper.SetConfigType(suffix)
		err = remoteViper.ReadRemoteConfig()
		if err == nil {
			// 将配置viper内存中的数据映射为全局配置结构体参数
			var moduleConfig config.AppConfig
			if err = remoteViper.Unmarshal(&moduleConfig); err == nil {
				global.AppConfig = &moduleConfig
				remoteConfig, _ := json.Marshal(moduleConfig)
				log.Printf("%+v", string(remoteConfig))
				log.Println("=== Viper 读取远程配置数据成功 ===")
				break
			}
		}
		log.Printf("=== Viper 读取远程配置数据失败, 第 %d 次重试: %s", i+1, err)
		time.Sleep(2 * time.Second) // 等待一段时间后重试
	}

	//// 创建一个互斥锁，以保护对 latestConfig 的并发访问
	//var mutex sync.Mutex
	//remoteProvider := remote.NewRemoteProvider(suffix)
	//watchRemoteConfigOnChannel := remoteProvider.WatchRemoteConfigOnChannel(remoteViper)
	//
	//go func(rc <-chan bool) {
	//	for {
	//		select {
	//		case <-rc: // 当配置变更时接收通知
	//			mutex.Lock()
	//			var moduleConfig config.ModuleConfig
	//			if err := remoteViper.Unmarshal(&moduleConfig); err != nil {
	//				log.Fatalf("从Viper远程更新数据失败: %+v", err)
	//			} else {
	//				global.ModuleConfig = &moduleConfig
	//				remoteConfig, err := json.Marshal(moduleConfig)
	//				if err != nil {
	//					log.Fatalf("序列化配置数据失败: %+v", err)
	//				} else {
	//					log.Printf("从Viper成功拉取并更新远程配置数据: %s", string(remoteConfig))
	//				}
	//			}
	//			mutex.Unlock()
	//		}
	//	}
	//}(watchRemoteConfigOnChannel)

	return remoteViper
}
